
-- if not GLOBAL.TheNet:GetIsClient() then return end
-- 上次游玩时间, 总游玩时间, 世界ID, [世界名称, IP, 端口, 密码]
local file_sys = require("libs/filehandle")
local ent_util = require("libs/entutil")
local t_util = require("libs/tableutil")
local BOX_PREFIX = "SRC_BOX_DATA_"
local BOX_TAIL = ".hxd"
local INV_PREFIX = "inv_"
local WORLD_PREFIX = "w_"
local NOTE_PREFIX = "v_"
local BUNDLE_PREFIX = "b_"

local note = "hx_note"
local idea = "hx_idea"

local baton,sticker

-- 注意：至少为3
local ceiling = tonumber(GetModConfigData("sw_memory")) or 20
local SimSeed

-- a:all_time   总游玩时间
-- e:en_time    进入世界的时间
-- b:bind_file  绑定的文件序号

local data_index = BOX_PREFIX .. "0" .. BOX_TAIL
local data_true = BOX_PREFIX.."两面包加芝士"..BOX_TAIL
local world_data = {}
local box_data = {}

local profile_show_smart_minisign = "SHOW_SMART_MINISIGN"


local show_smart_minisign = true
local show_note_name = GetModConfigData("wanda_rename")
local show_bundle_content = GetModConfigData("sw_bundle") and not IsInMODlist({"信息显示", "insight", "showme", "提示语句", "疼的放大镜"})
local show_box_highlight = GetModConfigData("sw_box") and not HasModName("insight")


local table_show_huxi_sign = {"treasurechest", "dragonflychest"}
local table_show_note_name = {"pocketwatch_recall", "pocketwatch_portal"}
local table_shadow_container = {"shadow_container"}
local table_show_bundle_content = {"bundle", "gift"}
local table_chester_container = {"chester", "hutch"}


local function CanEnableMinisign()
    return not HasModName("小木牌") and not HasModName("minisign") and GetModConfigData("sw_minisign")
end

-- 深度优先
local function PathRecursiver(searchBox, missingItem, path)
    if searchBox and searchBox == missingItem then
        return path
    end
    local container = ent_util:getContainer(searchBox)
    if container then
        local items = container:GetItems() or {}
        local new_path
        for slot, item in pairs(items)do
            local new_path = PathRecursiver(item, missingItem, path..slot)
            if new_path then
                return new_path
            end
        end
    end
end


local function GetEntPosID(inst)
    if type(inst) == "table" then
        local prefab_name = inst.prefab
        if table.contains(table_shadow_container, prefab_name) then
            return WORLD_PREFIX.."sc"
        elseif table.contains(table_chester_container, prefab_name) then
            return WORLD_PREFIX..prefab_name
        end
    end
    if not ent_util:isValid(inst) then return end

    local path
    if not inst:HasTag("INLIMBO") and not inst:HasTag("player") then
        local x,y,z = inst.Transform:GetWorldPosition()
        path = WORLD_PREFIX..string.format("%.2f_%.2f", x, z)
    else
        path = PathRecursiver(GLOBAL.ThePlayer, inst, INV_PREFIX)
        if not path then
            for _,equipslot in pairs(GLOBAL.EQUIPSLOTS or {})do
                path = PathRecursiver(GetEquippedItemFrom(equipslot), inst, INV_PREFIX..equipslot)
                if path then break end
            end
        end
        if not path then
            local inv =  GLOBAL.ThePlayer and GLOBAL.ThePlayer.replica and GLOBAL.ThePlayer.replica.inventory
            if inv then
                for container,stat in pairs(inv:GetOpenContainers()) do
                    if stat and not container:HasTag("INLIMBO") then
                        path = PathRecursiver(container, inst, GetEntPosID(container))
                        if path then break end
                    end
                end
            end
        end
    end
    return path
end



-----  智能小木牌
local function ShowSmartMinisign(ent)
    if not show_smart_minisign then return end
    local container = ent_util:getContainer(ent)
    if not ent_util:isValid(ent) or not container then return end

    local atlas, image =  ent_util:getAtlasAndImage(t_util:getMinValue(container:GetItems()))
    if not atlas or not image then
        local posid = GetEntPosID(ent)
        atlas = posid and box_data[posid] and box_data[posid].sa
        image = posid and box_data[posid] and box_data[posid].si
    end

    local sign = ent.huxi_sign
    if not sign or not sign:IsValid() then
        sign = GLOBAL.SpawnPrefab("huxi_sign")
        sign.entity:SetParent(ent.entity)
        ent.huxi_sign = sign
    end
    sign:draw(atlas, image)
end


local function SwitchShowSmartMinisign()
    if not CanEnableMinisign() then
        TIP("智能小木牌", "red", "无法启用, 原因：启用了服务器版本的智能小木牌", "chat")
        return
    end
    show_smart_minisign = not show_smart_minisign
    if show_smart_minisign then
        for _, ent in pairs(PlayerFindEnts())do
            if table.contains(table_show_huxi_sign, ent.prefab) then
                ShowSmartMinisign(ent)
            end
        end
    else
        for _, ent in pairs(PlayerFindEnts(nil, {"sign", "huxi", "FX"},{}))do
            ent:Remove()
        end
    end
    SaveModData(profile_show_smart_minisign, show_smart_minisign)
    TIP("智能小木牌", "white", show_smart_minisign)
end

if GetModConfigData("sw_minisign") == "biubiu" then
    DEAR_BTNS:AddDearBtn(GLOBAL.GetInventoryItemAtlas("minisign_picketwhite_drawn.tex"), "minisign_picketwhite_drawn.tex", "智能小木牌", "慕斯专享功能, 点击可选择不显示木牌或显示木牌", true, SwitchShowSmartMinisign)
end
AddBindBtn("sw_minisign", SwitchShowSmartMinisign)


-- 旺达表命名
local function SayMyName(inst, name, id)
    if ent_util:isValid(inst) and type(name) == "string" then
        local strs = ""
        if inst.prefab then
            strs = GLOBAL.STRINGS.NAMES[string.upper(inst.prefab)]
            if strs and string.len(name) ~= 0  then               
                inst.name = strs.."["..name.."]"
                inst[id] = name
            end
        end
    end
end

local function HoldTheName(_, data)
    if data and data.item then
        if baton and table.contains(table_show_note_name, data.item.prefab) then
            SayMyName(data.item, baton, note)
            baton = nil
        end
        if sticker and table.contains(table_show_bundle_content, data.item.prefab) then
            SayMyName(data.item, sticker, idea)
            sticker = nil
        end
    end
end

local function ShowNoteName(ent)
    if not show_note_name then return end
    local container = ent_util:getContainer(ent)
    local posid = GetEntPosID(ent)
    if posid and container then
        for slot, item in pairs(container:GetItems())do
            if table.contains(table_show_note_name, item.prefab) then
                local item_data = box_data[posid]
                if item_data then
                    SayMyName(item, item_data[NOTE_PREFIX..slot], note)
                end
            end
        end
    end
end
if show_note_name then
    for _,watch_name in pairs(table_show_note_name)do
        AddPrefabPostInit(watch_name, function(inst)
            inst:DoTaskInTime(0.5, function(inst)
                local posid = GetEntPosID(inst)
                if posid and not inst:HasTag("INLIMBO") and type(box_data) == "table" then
                    local item_data = box_data[posid]
                    if item_data then
                        SayMyName(inst, item_data[NOTE_PREFIX], note)
                    end
                end
            end)
    
            
            -- 一个小bug：丢在刷新区域却通过服务器离开会丢失数据
            inst:ListenForEvent("onremove", function(inst)
                local posid = GetEntPosID(inst)
                local name = inst[note]
                if name then
                    if posid and type(box_data) == "table" and not inst:HasTag("INLIMBO") then
                        box_data[posid] = {
                            [NOTE_PREFIX] = name
                        }
                    else
                        baton = name
                        GLOBAL.ThePlayer:DoTaskInTime(0.3, function()
                            baton = nil
                        end)
                    end
                end
            end)
        end)
    end
end

-- 打包纸记忆（其实就是旺达表命名，不过不提供自己改备注的接口
local function ShowBundleContent(ent)
    if not show_bundle_content then return end
    local container = ent_util:getContainer(ent)
    local posid = GetEntPosID(ent)
    if posid and container then
        for slot, item in pairs(container:GetItems())do
            if table.contains(table_show_bundle_content, item.prefab) then
                local item_data = box_data[posid]
                if item_data then
                    SayMyName(item, item_data[BUNDLE_PREFIX..slot], idea)
                end
            end
        end
    end
end


if show_bundle_content then
    local __ConfirmExecutionOnceTheLock
    AddClassPostConstruct("screens/playerhud", function(self)
        local __OpenContainer = self.OpenContainer
        self.OpenContainer = function(HUD, ent, ...)
            __OpenContainer(HUD, ent, ...)
            if __ConfirmExecutionOnceTheLock then return end
            local container = ent_util:getContainer(ent)
            if container and ent:HasTag("bundle") then
                local widget = container:GetWidget()
                local _fn = widget and widget.buttoninfo and widget.buttoninfo.fn
                if _fn then
                    __ConfirmExecutionOnceTheLock = true
                    widget.buttoninfo.fn = function(ent, ...)
                        container = ent_util:getContainer(ent)
                        if container then
                            local items = container:GetItems() or {}

                            local sticker_table = {}
                            for _, item in pairs(items)do
                                local name = item:GetBasicDisplayName()
                                local stacksize = ent_util:getStacksize(item)
                                if stacksize == 1 then
                                    table.insert(sticker_table, name)
                                else
                                    table.insert(sticker_table, name.."(".. ent_util:getStacksize(item) ..")")
                                end
                            end
                            sticker = table.concat(sticker_table,",")
                            GLOBAL.ThePlayer:DoTaskInTime(3, function()
                                sticker = nil
                            end)
                        end
                        _fn(ent, ...)
                    end
                end
            end
        end
    end)

    for _,bundle_name in pairs(table_show_bundle_content)do
        AddPrefabPostInit(bundle_name, function(inst)
            inst:DoTaskInTime(0.5, function(inst)
                local posid = GetEntPosID(inst)
                if posid and not inst:HasTag("INLIMBO") and type(box_data) == "table" then
                    local item_data = box_data[posid]
                    if item_data then
                        SayMyName(inst, item_data[BUNDLE_PREFIX], idea)
                    end
                end
            end)
    
            
            -- 一个小bug：丢在刷新区域却通过服务器离开会丢失数据
            inst:ListenForEvent("onremove", function(inst)
                local posid = GetEntPosID(inst)
                local name = inst[idea]
                if name and posid and type(box_data) == "table" and not inst:HasTag("INLIMBO") then
                    box_data[posid] = {
                        [BUNDLE_PREFIX] = name
                    }
                end
            end)
        end)
    end
end







-- 核心
local function ContainerPostConstruct(self, ent)
    if not self.type and not self.__ConfirmToInitializeTheLock then
        self.__ConfirmToInitializeTheLock = true

        if ent and ent.OnEntityReplicated then
            local _OnEntityReplicated = ent.OnEntityReplicated
            ent.OnEntityReplicated = function(...)
                _OnEntityReplicated(...)
                ContainerPostConstruct(self, ent)
            end
        end
    end

    self.hx_record_data = function()
        local posid = GetEntPosID(ent)
        if not posid then 
            return
        elseif self:IsEmpty() or self:GetNumSlots()<5 then
            box_data[posid] = nil
            return 
        end

        local items = self:GetItems() or {}
        local container_data = {
            f = self:IsFull() and 1 or 0
        }

        if table.contains(table_show_huxi_sign, ent.prefab) and not posid:starts(INV_PREFIX) then
            container_data.sa, container_data.si = ent_util:getAtlasAndImage(t_util:getMinValue(items))
        end


        for slot,item in pairs(items)do
            container_data[slot] = item.prefab
            container_data[NOTE_PREFIX..slot] = item[note]
            container_data[BUNDLE_PREFIX..slot] = item[idea]
        end
        
        
        box_data[posid] = container_data
        -- file_sys:MapToJsonLine(data_true, box_data)
    end


    local _DetachOpener = self.DetachOpener
    self.DetachOpener = function(self, ...)
        self.hx_record_data()
        _DetachOpener(self, ...)
    end

    if show_note_name or show_bundle_content then
        local _Open = self.Open
        self.Open = function(self, ...)
            _Open(self, ...)
            ShowNoteName(ent)
            ShowBundleContent(ent)
        end
        self.inst:ListenForEvent("itemget", HoldTheName)
    end

    if table.contains(table_show_huxi_sign, ent.prefab) then
        local __Open = self.Open
        self.Open = function(self, ...)
            __Open(self, ...)
            ShowSmartMinisign(ent)
        end

        self.inst:ListenForEvent("itemget", ShowSmartMinisign)
        self.inst:ListenForEvent("itemlose", ShowSmartMinisign)
        ent:DoTaskInTime(0.5, ShowSmartMinisign)
    end
end

local function InventoryPostConstruct(self, ent)
    if not self.type and not self.__ConfirmToInitializeTheLock then
        self.__ConfirmToInitializeTheLock = true

        if ent and ent.OnEntityReplicated then
            local _OnEntityReplicated = ent.OnEntityReplicated
            ent.OnEntityReplicated = function(...)
                _OnEntityReplicated(...)
                InventoryPostConstruct(self, ent)
            end
        end
    end

    self.hx_record_data = function()
        local posid = GetEntPosID(ent)
        if not posid then return end

        local items = self:GetItems() or {}
        local inv_data = {}
        for slot,item in pairs(items)do
            inv_data[NOTE_PREFIX..slot] = item[note]
            inv_data[BUNDLE_PREFIX..slot] = item[idea]
        end
        
        
        box_data[posid] = inv_data
        -- file_sys:MapToJsonLine(data_true, box_data)
    end

    if show_note_name or show_bundle_content then
        local __DetachClassified = self.DetachClassified
        self.DetachClassified = function(self, ...)
            self.hx_record_data()
            __DetachClassified(self, ...)
        end
        self.inst:ListenForEvent("itemget", HoldTheName)
    end
end


if GLOBAL.TheNet:GetIsClient() then
    AddClassPostConstruct("components/container_replica", ContainerPostConstruct)
    AddClassPostConstruct("components/inventory_replica", InventoryPostConstruct)
    -- 算了，先禁了无洞穴模式
-- else
--     -- 无洞穴模式性能很差
--     AddPrefabPostInitAny(function(inst)
--         if inst.components and inst.components.container then
--             ContainerPostConstruct(inst.components.container)
--         end
--     end)
--     AddPrefabPostInit("world", function(world)
--         world:ListenForEvent("playeractivated", function(world, player)
--             if player == GLOBAL.ThePlayer then
--                 if player.components and player.components.inventory then
--                     InventoryPostConstruct(player.components.inventory)
--                 end
--             end
--         end)
--     end)
end


local function InitializationOfMemory()
    if not SimSeed then
        return file_sys:LogAddFile("记忆力初始化失败")
    end
    local now = os.time()
    world_data = file_sys:MapFromJsonLine(data_index)
    if type(world_data[SimSeed]) == "table" then
        world_data[SimSeed].e = now
    else
        world_data[SimSeed] = {e = now}
    end

    local bind_count = table.count(world_data)
    if world_data[SimSeed].b then
    elseif bind_count <= ceiling then
        world_data[SimSeed].b = bind_count
    else
        local tmp_t = {}
        for w_seed, w_data in pairs(world_data) do
            table.insert(tmp_t, {a = w_data.a or 0, b = w_data.b, e = w_data.e or now, s = w_seed})
        end
        table.sort(tmp_t, function(x, y) return x.a < y.a end)
        local tmp_t2 = {}
        for i=1,math.ceil(ceiling/2) do
            table.insert(tmp_t2, tmp_t[i])
        end
        table.sort(tmp_t2, function (x,y)return x.e < y.e  end)
        world_data[SimSeed].b = tmp_t2[1].b or ceiling+1
        -- world_data[tmp_t2[1].s] = nil        -- 我都忘了这个干什么的了
    end
    
    file_sys:MapToJsonLine(data_index, world_data)
    local bind_id = world_data[SimSeed].b
    data_true = BOX_PREFIX..bind_id..BOX_TAIL
    box_data = file_sys:MapFromJsonLine(data_true)
end


local function SaveWorldData()
    if show_note_name or show_bundle_content then
        local inv = GLOBAL.ThePlayer and GLOBAL.ThePlayer.replica and GLOBAL.ThePlayer.replica.inventory
        if inv and inv.hx_record_data then inv:hx_record_data() end


        local ents = PlayerFindEnts()
        for _, ent in pairs(ents)do
            if table.contains(table_show_bundle_content, ent.prefab)
            or table.contains(table_show_note_name, ent.prefab) then
                local posid = GetEntPosID(ent)
                if posid then
                    box_data[posid] = {
                        [NOTE_PREFIX] = ent[note],
                        [BUNDLE_PREFIX] = ent[idea]
                    }
                end
            end
        end
    end
    


    if SimSeed and type(world_data[SimSeed]) == "table" then
        local last_a = world_data[SimSeed].a or 0
        world_data[SimSeed].a = last_a + os.time() - (world_data[SimSeed].e or os.time())
        world_data[SimSeed].e = os.time()
        file_sys:MapToJsonLine(data_index, world_data)
        -- 重要
        file_sys:MapToJsonLine(data_true, box_data)
    end
end



local dyeing_containers = {}
local function ModifyContainerColor(container, reset, full)
    if container and container.AnimState then
        if reset then
            container.AnimState:SetMultColour(1,1,1,1)
        else
            if full then
                container.AnimState:SetMultColour(1,0,1,1)
            else
                container.AnimState:SetMultColour(0,1,0,1)
            end
            table.insert(dyeing_containers, container)
        end
    end
end

local coastline = {}
local tile_data = {}
local turf_size = 4
local turf_grid_radius = 10
local coastline_visable = false
local tile_ocean_shore = {GLOBAL.GROUND.OCEAN_START, GLOBAL.GROUND.OCEAN_COASTAL, GLOBAL.GROUND.OCEAN_COASTAL_SHORE}

local function ClearAllContainersColor()
    for _, dye_cont in pairs(dyeing_containers)do
        ModifyContainerColor(dye_cont, true)
    end
    dyeing_containers = {}

    
    if coastline_visable then 
        for _, line in pairs(coastline) do
            line:Hide()
        end
        coastline = {}
        coastline_visable = false
    end
end


local function ShowMeetContainersWithPrefab(prefab)
    ClearAllContainersColor()
    local container_ents = PlayerFindEnts(40) -- {"_container", "chest", "structure"}
    for _, container_ent in pairs(container_ents)do
        if container_ent:HasTag("_container") then
            local posid = GetEntPosID(container_ent)
            local data = posid and box_data[posid]
            if type(data) == "table" then
                for _,thing in pairs(data)do
                    if thing == prefab then
                        if data.f == 1 then
                            ModifyContainerColor(container_ent, false, true)
                            ModifyContainerColor(container_ent.huxi_sign, false, true)
                        else
                            ModifyContainerColor(container_ent, false)
                            ModifyContainerColor(container_ent.huxi_sign, false)
                        end
                        break
                    end
                end
            end
        end
        if container_ent.prefab == prefab then
            ModifyContainerColor(container_ent, false)
        end
    end
    
    -- 显示海岸线
    if prefab == "dock_kit" then
        local map = GLOBAL.TheWorld.Map

        coastline_visable = true
        local center_x, _, center_z = map:GetTileCenterPoint(GLOBAL.ThePlayer.Transform:GetWorldPosition())
        local radius = turf_grid_radius * turf_size
        local count = 0

        for x = center_x - radius, center_x + radius + turf_size, turf_size do
            for z = center_z - radius, center_z + radius + turf_size, turf_size do
                tile_data[count] = map:GetTileAtPoint(x, 0, z)
                count = count+1
            end
        end

        count = 0
        local z_num = 2*(turf_grid_radius+1)
        for x = 0, z_num-2, 1 do
            for z = 0, z_num-2, 1 do
                local c_id = z + z_num*x
                local pos_x = center_x + turf_size*(x - turf_grid_radius)
                local pos_z = center_z + turf_size*(z - turf_grid_radius)
                local diff_flag = table.contains(tile_ocean_shore, tile_data[c_id])
                local r_flag = table.contains(tile_ocean_shore, tile_data[c_id+1])
                local d_flag = table.contains(tile_ocean_shore, tile_data[c_id+z_num])
                if (diff_flag and {not r_flag} or {r_flag})[1] then
                    coastline[count] = GLOBAL.SpawnPrefab("hline")
                    coastline[count].Transform:SetPosition(pos_x, 0, pos_z+0.5*turf_size)
                    coastline[count].Transform:SetRotation(90)
                    count = count + 1
                end
                if (diff_flag and {not d_flag} or {d_flag})[1]   then
                    coastline[count] = GLOBAL.SpawnPrefab("hline")
                    coastline[count].Transform:SetPosition(pos_x+0.5*turf_size, 0, pos_z)
                    count = count + 1
                end
            end
        end
    end
end


local __ConfirmPlayerInitializationTheLock
AddPrefabPostInit("world", function(world)
    world:ListenForEvent("playeractivated", function(world, player)
        if player == GLOBAL.ThePlayer then
            if not __ConfirmPlayerInitializationTheLock then
                -- player:ListenForEvent("refreshinventory", function()end)
                __ConfirmPlayerInitializationTheLock = true
                SimSeed = GetPlayerSeed()
                WORLD_PREFIX = world:HasTag("cave") and "c_" or "w_"
                InitializationOfMemory()
            end
            ShowNoteName(player)
            ShowBundleContent(player)
            player:WatchWorldState("startday", SaveWorldData)

            if show_box_highlight then
                player:ListenForEvent("refreshinventory", function()
                    if player.replica.inventory then
                        local active_item = player.replica.inventory:GetActiveItem()
                        if active_item then
                            ShowMeetContainersWithPrefab(active_item.prefab)
                        else
                            ClearAllContainersColor()
                        end
                    end
                end)
            end
        end
    end)
    local result = LoadModData(profile_show_smart_minisign)
    show_smart_minisign = (type(result) == "nil" or result) and CanEnableMinisign()
end)

local _DoRestart = GLOBAL.DoRestart
function GLOBAL.DoRestart()
    SaveWorldData()
    _DoRestart()
end

local _MigrateToServer = GLOBAL.MigrateToServer
function GLOBAL.MigrateToServer(ip, port, ...)
    SaveWorldData()
    _MigrateToServer(ip, port, ...)
end


-- 我抄我自己

local sw_rename = false
local funcTip = "旺达表命名"

local function AdaptTIP(sw)
    if sw then
        TIP(funcTip, "yellow", "已开启, 右键单击 溯源表或裂缝表 进行命名或重命名", "chat")
    else
        TIP(funcTip, "red", "已关闭", "chat")
    end
end

local writeablescreen
local WriteableWidget = require "screens/TMIP_writeablewidget"
local writeable_widget_args = {
    animbank = "ui_board_5x3",
    animbuild = "ui_board_5x3",
    menuoffset = GLOBAL.Vector3(6, -70, 0),
    cancelbtn = {
        text = GLOBAL.STRINGS.UI.TRADESCREEN.CANCEL,
        cb = function()
            GLOBAL.ChatHistory:AddToHistory(GLOBAL.ChatTypes.Message, nil, nil, funcTip, "取消", GLOBAL.PLAYERCOLOURS.YELLOW)
        end,
        control = GLOBAL.CONTROL_CANCEL
    },
    acceptbtn = {
        text = GLOBAL.STRINGS.UI.TRADESCREEN.ACCEPT,
        cb = function(w, target)
            SayMyName(target, w:GetText(), note)
        end,
        control = GLOBAL.CONTROL_ACCEPT
    }
}
local function OpenWriteScreen(target)
    if writeablescreen then
        writeablescreen:KillAllChildren()
        writeablescreen:Kill()
        writeablescreen = nil
    end
    writeablescreen = WriteableWidget(writeable_widget_args, target)
    GLOBAL.ThePlayer.HUD:OpenScreenUnderPause(writeablescreen)
    if GLOBAL.TheFrontEnd:GetActiveScreen() == writeablescreen then
        writeablescreen.edit_text:SetEditing(true)
    end
end

local function SwitchShowNoteName()
    sw_rename = not sw_rename
    AdaptTIP(sw_rename)
end
if GetModConfigData("wanda_rename") == "biubiu" then
DEAR_BTNS:AddDearBtn(GLOBAL.GetInventoryItemAtlas("pocketwatch_recall.tex"), "pocketwatch_recall.tex", funcTip, "我丢你老表啊~~", true, SwitchShowNoteName)
end
AddBindBtn("wanda_rename", SwitchShowNoteName)

AddClassPostConstruct("widgets/invslot", function(self)
    local _OnControl = self.OnControl
    self.OnControl = function(self, control, down, ...)
        if down and control == GLOBAL.CONTROL_SECONDARY and not GLOBAL.TheInput:IsControlPressed(GLOBAL.CONTROL_FORCE_TRADE) 
        and sw_rename 
        and self.tile and self.tile.item and table.contains(table_show_note_name, self.tile.item.prefab)
        then
            OpenWriteScreen(self.tile.item)
            sw_rename = false
            AdaptTIP(sw_rename)
        else
            return _OnControl(self, control, down, ...)
        end
    end
end)


-- 更改显示
local str_rename = GLOBAL.STRINGS.KITCOON_NAMING.MENU_ACCEPT
local str_re_rename = GLOBAL.STRINGS.ACTIONS.RESETMINE..str_rename
AddComponentPostInit("playeractionpicker", function(self)
    local _GetInventoryActions = self.GetInventoryActions
    self.GetInventoryActions = function(self, item, ...)
        local inv_actions = _GetInventoryActions(self, item, ...)
        if sw_rename and table.contains(table_show_note_name, item.prefab) then
            for _, inv_action in pairs(inv_actions) do
                if inv_action.action == GLOBAL.ACTIONS.LOOKAT or inv_action.action == GLOBAL.ACTIONS.CAST_POCKETWATCH then
                    if item[note] then
                        inv_action.GetActionString = function()
                            return str_re_rename
                        end
                    else
                        inv_action.GetActionString = function()
                            return str_rename
                        end
                    end
                end
            end
        end
        return inv_actions
    end
end)


if not show_box_highlight then
    return
end

local pointer
-- is_display
---- true:展示该prefab
---- false:移除该prefab的展示
local function ShowPrefabView(prefab, is_display)
    if is_display then
        pointer = prefab
    else
        if pointer == prefab then
            pointer = nil
        end
    end
    ShowMeetContainersWithPrefab(pointer)
end

AddClassPostConstruct("widgets/ingredientui", function (self, ...)
    local _OnGainFocus = self.OnGainFocus
    function self.OnGainFocus(self, ...)
        local prefab = self.ing and self.ing.texture and self.ing.texture:match('[^/]+$'):gsub('%.tex$', '')
        local player = self.parent and self.parent.parent and self.parent.parent.owner

        if prefab and player then
            ShowPrefabView(prefab, true)
        end
        if _OnGainFocus then
            return _OnGainFocus(self, ...)
        end
    end

    local _OnLoseFocus = self.OnLoseFocus
    function self.OnLoseFocus(self, ...)
        local prefab = self.ing and self.ing.texture and self.ing.texture:match('[^/]+$'):gsub('%.tex$', '')
        local player = self.parent and self.parent.parent and self.parent.parent.owner

        if prefab and player then
            ShowPrefabView(prefab, false)
        end
        if _OnLoseFocus then
            return _OnLoseFocus(self, ...)
        end
    end
end)

-- 侧边栏显示
AddClassPostConstruct("widgets/redux/craftingmenu_pinslot", function (self, ...)
    local _OnGainFocus = self.OnGainFocus
    function self.OnGainFocus(self, ...)
        ShowPrefabView(self.recipe_name, true)
        return _OnGainFocus(self, ...)
    end    
    
    local _OnLoseFocus = self.OnLoseFocus
    function self.OnLoseFocus(self, ...)
        ShowPrefabView(self.recipe_name, false)
        return _OnLoseFocus(self, ...)
    end
end)
